﻿using System;
using System.Linq;
using System.Web.Mvc;
using System.Web.Security;
using APMS.WebSite.Common;
using APMS.WebSite.Models.DataStore;
using APMS.WebSite.Models.ViewData.Pages;
using System.Collections.Generic;

namespace APMS.WebSite.Controllers
{
    /// <summary>
    /// UserController controls all Views related to user operation which are:
    /// * Index (/User/) - Default action, return Login action
    /// * Login (/User/Login/) - Login to the system
    /// * Logout (/User/Logout/) - Logout from the system
    /// * View (/User/View/{id}) - View User Profile
    /// * MORE
    /// </summary>
    /// <version>$Revision$ $Date$</version>
    /// <history>
    /// <record>09/15/2008. raQuiam - Created this file</record>
    /// </history>
    [HandleError]
    public class UserController : BaseController
    {
        #region Keys for ViewData

        #endregion

        /// <summary>
        /// Default action
        /// </summary>
        /// <returns></returns>
        public ActionResult Index()
        {
            return View("Login");
        }

        public ActionResult Delete(string id)
        {
            //throw new NotImplementedException();
            MySQLDataStore db = DataStoreFactory.GetMySQLDataStore();

            string deleteingUser = "admin"; 
            try
            {
                ProjectUser deleteProjectUser = db.ProjectUser.Single(p => p.UserName == deleteingUser);
                db.ProjectUser.Remove(deleteProjectUser);
                db.SubmitChanges();
            }
            catch (InvalidOperationException ex)
            {
                System.Console.WriteLine("called on set with zero items");
            }
            ////////////////////// DELETE DATA

            return Index();

            return View("test");
        }

        #region Login Action

        /// <summary>
        /// Authenticate user with given username and password
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <param name="rememberMe"></param>
        /// <param name="ReturnUrl"></param>
        /// <returns></returns>
        public ActionResult Login()
        {
            if (Request.HttpMethod == Constants.HttpMethod.POST)
            {
                #region Login from post parameter

                // Extract values from Form
                string userName = Request.Form["userName"];
                string password = Request.Form["password"];
                bool rememberMe = !String.IsNullOrEmpty(Request.Form["rememberMe"]) 
                    ? Convert.ToBoolean(Request.Form["rememberMe"]) : false;
                string returnUrl = Request.QueryString["ReturnUrl"];

                if (this.IsValidLoginArgument(userName, password))
                {
                    // TODO: Move to UserService
                    MySQLDataStore db = DataStoreFactory.GetMySQLDataStore();
                    var query =
                        from user in db.Users
                        where
                            user.UserName == userName &&
                            user.PassWord == password
                        select user;
                    bool isValidUser = (query.Count() > 0) ? true : false;

                    if (isValidUser)
                    {
                        return AuthenticateAndRedirect(userName, returnUrl);
                    }
                    else
                    {
                        // TODO: Show error message with jQuery
                        //Response.Write("Invalid Username or password!");
                        ViewData[KEY_ERROR_MSG] = "<b>Login faild!</b> Make sure you have entered the right user name and password!";
                    }
                }
                #endregion
            }

           return View("Login");
        }

        /// <summary>
        /// Authenticate current user by add information to UserProfile object
        /// then redirect to appropiate URL
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        private ActionResult AuthenticateAndRedirect(string userName, string returnUrl)
        {
            FormsAuthentication.SetAuthCookie(userName, false);

            // Instantiate UserProfile object tied to current session
            UserProfile.Initialize(userName);

            if (!String.IsNullOrEmpty(returnUrl))
                return Redirect(returnUrl);

            return RedirectToAction("List", "Project");
        }

        private bool IsValidLoginArgument(string userName, string password)
        {
            return !(string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(password));
        }
        #endregion

        #region Logout Action
        /// <summary>
        /// Unauthenticated user and redirect to Login page
        /// </summary>
        /// <returns></returns>
        public ActionResult Logout()
        {
            FormsAuthentication.SignOut();
            return RedirectToAction("Login", "User");
        }
        #endregion

        #region Update action
        /// <summary>
        /// Update target User
        /// </summary>
        /// <param name="id">ID of user to be updated</param>
        /// <returns></returns>
        public ActionResult Update(string id)
        {
            // Initialize data required by master page
            ActionResult exception = base.InitializeAction();
            if (exception != null)
                return exception;

            // Ser Window Title
            base.SetTitle("User Profile | " + id);

            MySQLDataStore db = DataStoreFactory.GetMySQLDataStore();

            #region SELECT * FROM user WHERE user.UserName = '{currentUser}'
            string findUser = id;
            var query =
                from user in db.Users
                where
                    user.UserName == findUser
                select user;
            #endregion

            // Find all projects to create avialable project list
            var query2 =
                from allProject in db.Project
                select allProject;
            //List<Project> allProjectList = query2.ToList<Project>();

            // Find user participated project to pre-select the project list
            var query3 =
                from selectedProject in db.ProjectUser
                where selectedProject.UserName == findUser
                select selectedProject;
            //List<ProjectUser> selectedProjectList = query3.ToList<ProjectUser>();

            // Prepare ViewData
            ManageUserViewData viewData = new ManageUserViewData();
            viewData.CurrentUser = query.First<Users>();
            viewData.AllProjects = query2.ToList<Project>();
            viewData.SelectedProjects = query3.ToList<ProjectUser>();

            // If POST means UPDATE the value from Request.Form to DB
            // If GET means VIEW the value from DB
            if (Request.HttpMethod == Constants.HttpMethod.POST)
            {
                #region Update record back to DB
                viewData.CurrentUser.PassWord = Request.Form["password"];
                viewData.CurrentUser.Email = Request.Form["email"];
                viewData.CurrentUser.FirstName = Request.Form["firstName"];
                viewData.CurrentUser.LastName = Request.Form["lastName"];
                viewData.CurrentUser.ModifyDate = DateTime.Now;

                viewData.IsCurrentUserUpdate = true;

                db.SubmitChanges();
                #endregion
            }
            else
            {
                viewData.IsCurrentUserUpdate = false;
            }

            return View("Update", viewData);
        }

        /// <summary>
        /// Callback Action
        /// </summary>
        /// <param name="projectId"></param>
        public void AddUserProject(int projectId, string userName)
        {
            #region Verify sent parameters
            if (String.IsNullOrEmpty(Convert.ToString(projectId)) || String.IsNullOrEmpty(userName))
            {
                Response.Write("ERROR! projectId OR userName is empty");
                return;
            }
            #endregion

            MySQLDataStore db = DataStoreFactory.GetMySQLDataStore();

            //Is project avalible
            var querys =
                from project in db.Project
                where
                    project.ProjectID == projectId
                select project;
            //Is this user avalible in this project
            var querys1 =
                from projectUser in db.ProjectUser
                where
                    projectUser.UserName == userName &&
                    projectUser.ProjectID == projectId
                select projectUser;
            //Is this user avalible in system
            var querys2 =
                from user in db.Users
                where
                    user.UserName == userName
                select user;
            if (querys.Count() > 0 && querys2.Count() > 0 && querys1.Count() <= 0)
            {
                try
                {
                    // new project
                    Project currentProject = querys.First();

                    ProjectUser newProjectUser = new ProjectUser();
                    newProjectUser.ProjectID = projectId;
                    newProjectUser.JoinDate = DateTime.Now;
                    newProjectUser.UserName = userName;

                    //db.ProjectUser.Add(newProjectUser);
                    db.ProjectUser.InsertOnSubmit(newProjectUser);
                    db.SubmitChanges();
                }
                catch (Exception ex)
                {
                    Response.Write("ERROR:" + ex.Message);
                }
            }
            //else
            //{
            //    Response.Write("ERROR: Cannot add this user to the selected project");
            //    return;
            //}

            Response.Write("success");
        }

        /// <summary>
        /// Callback Action
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="userName"></param>
        public void RemoveUserProject(int projectId, string userName)
        {
            #region Verify sent parameters
            if (String.IsNullOrEmpty(Convert.ToString(projectId)) || String.IsNullOrEmpty(userName))
            {
                Response.Write("ERROR! projectId OR userName is empty");
                return;
            }
            #endregion

            MySQLDataStore db = DataStoreFactory.GetMySQLDataStore();

            var query =
                 from projectUser in db.ProjectUser
                 where
                     projectUser.ProjectID == projectId &&
                     projectUser.UserName == userName
                 select projectUser;

            if (query.Count() > 0)
            {
                try
                {
                    ProjectUser deleteuser = query.First();
                    //db.ProjectUser.DeleteAllOnSubmit(query);
                    //db.ProjectUser.RemoveAll(query);
                    db.ProjectUser.DeleteOnSubmit(deleteuser);
                    db.SubmitChanges();
                    //deleteProject(projectId);
                }
                catch (InvalidOperationException ex)
                {
                    Response.Write("ERROR: " + ex.Message);
                    return;
                }
            }
            else
            {
                Response.Write("ERROR: User is not belong to this project OR this project has been deleted, try to refresh the browser");
                return;
            }

            Response.Write("success");
        }
        #endregion

        #region Create Action
        /// <summary>
        /// Create new User
        /// </summary>
        /// <returns>ViewResult if creation is succeed, message in ViewData[KEY_ERROR_MSG] otherwise</returns>
        public ActionResult Create()
        {
            // Ser Window Title
            base.SetTitle("Register New User");

            // Prepare ViewData
            ManageUserViewData viewData = new ManageUserViewData();

            // If POST means UPDATE the value from Request.Form to DB
            // If GET means VIEW the value from DB
            if (Request.HttpMethod == Constants.HttpMethod.POST)
            {
                #region Create new record in DB

                #region Extract values from Form
                string userName = Request.Form["userName"];
                string password = Request.Form["password"];
                string firstName = Request.Form["firstName"];
                string lastName = Request.Form["lastName"];
                string email = Request.Form["email"];
                #endregion

                // TODO: cross validation in server-side, avoid null value in DB

                // Prepare to INSERT by Linq
                MySQLDataStore db = DataStoreFactory.GetMySQLDataStore();

                Users newUser = new Users();
                newUser.UserName = userName;
                newUser.PassWord = password;
                newUser.FirstName = firstName;
                newUser.LastName = lastName;
                newUser.Email = email;
                newUser.AddDate = DateTime.Now;
                newUser.ModifyDate = DateTime.Now;

                viewData.CurrentUser = newUser;
                viewData.IsCurrentUserUpdate = true;

                //db.Users.Add(newUser);
                db.Users.InsertOnSubmit(newUser);
                db.SubmitChanges();
                #endregion
            }
            else
            {
                viewData.IsCurrentUserUpdate = false;
            }

            return View("Create", viewData);
        }
        #endregion
    }
}
